package com.pdd.article.server.model.article.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.pdd.article.enums.WebResultEmun;
import com.pdd.article.response.ResponseResult;
import com.pdd.article.server.commons.util.StrUtil;
import com.pdd.article.server.commons.yml.InterfaceConfig;
import com.pdd.article.server.commons.yml.UploadConfig;
import com.pdd.article.server.model.article.ArticleProcess;
import com.pdd.article.server.model.image.ImageProcess;
import com.pdd.commons.entity.dto.PublishArticleForm;
import com.pdd.commons.entity.vo.Article_Vo;
import com.pdd.commons.entity.vo.Blog_Image_Vo;
import com.pdd.commons.response.ResponseEntity;
import com.pdd.commons.utils.PublicKey;
import com.pdd.commons.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.safety.Whitelist;
import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.util.HtmlUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author:liyangpeng
 * @date:2019/6/20 14:21
 */
@Component
@Slf4j
public class ArticleProcessImpl implements ArticleProcess {

    @Autowired
    private InterfaceConfig interfaceConfig;
    @Autowired
    private UploadConfig uploadConfig;
    @Autowired
    private ImageProcess imageProcess;
    @Autowired
    private RedisUtils redisUtils;
    /**
     * xss白名单
     */
    private static final Whitelist whitelist = Whitelist.basicWithImages();

    /**
     * 配置过滤化参数,不对代码进行格式化
     */
    private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);

    /**
     * xss过滤
     * @param html
     * @return
     */
    @Override
    public String XSSFilter(String html) {
        if(!StringUtils.isEmpty(html)){
            html=html.trim();
            //xss过滤
            html=Jsoup.clean(html,"",whitelist,outputSettings);
            //a标签外链接过滤
            Document document=Jsoup.parse(html);
            Elements elements=document.select("a");
            if(elements!=null&&elements.size()>0){
                for (Element a: elements){
                    //a标签链接改为站内确认后再访问链接
                    if(!StringUtils.isEmpty(a.attr("href"))){
                        a.attr("href",interfaceConfig.getContentLink()+"?src="+a.attr("href"));
                    }
                }
            }
            return document.body().html();
        }
        return null;
    }

    /**
     * xss过滤
     * @param content
     * @return
     */
    public String XSSClean(String content){
        if(!StringUtils.isEmpty(content)){
            content=content.trim();
            //xss过滤(直接转义)
            content=HtmlUtils.htmlEscape(content);
        }
        return content;
    }
    /**
     * 图片处理
     * @return
     */
    @Override
    public ResponseEntity imageProcess(Document document, boolean isWmk) {
        List<Blog_Image_Vo> imgList=new ArrayList<>();
        Elements elements=document.select("img");
        for (int i = 0; i < elements.size(); i++) {
            Element img=elements.get(i);
            //如果图片链接为外网链接则先下载
            if(img.attr("src").indexOf(uploadConfig.getAccesshost())==-1){
                ResponseEntity imgDownload=imageProcess.downLoadImage(img.attr("src"));
                if(!imgDownload.isSuccess()){
                    return ResponseResult.RETURN_ERROR("正文第"+(i+1)+"张图片下载失败");
                }
                JSONObject path=(JSONObject)imgDownload.getData();
                String accessPath=uploadConfig.getAccesshost()+uploadConfig.getAccess()+path.getString("path").replace(uploadConfig.getSavePath(),"");
                //正常替换原文链接变成站内访问链接
                img.attr("src",accessPath);
            }
            //图片水印 压缩 上传 包装返回
            ResponseEntity comUpload=imageProcess.compressedUpload(img.attr("src"),isWmk,"摇头蘸酱");
            if(!comUpload.isSuccess()){
                return ResponseResult.RETURN_ERROR("正文第"+(i+1)+"张图片压缩上传失败");
            }
            //取回返回结果
            Blog_Image_Vo blog_image_vo=(Blog_Image_Vo) comUpload.getData();
            //如果存在水印图则直接替换原文为水印图
            if(!StringUtils.isEmpty(blog_image_vo.getWmk())){
                img.attr("src",blog_image_vo.getWmk());
            }else{
                img.attr("src",blog_image_vo.getSrc());
            }
            imgList.add(blog_image_vo);
        }
        return ResponseResult.Return(imgList);
    }

    /**
     * 正文处理
     * @param publishArticleForm
     * @return
     */
    @Override
    public ResponseEntity processArticle(PublishArticleForm publishArticleForm) {
        Article_Vo article_vo=new Article_Vo();
        //xss过滤
        String content=XSSFilter(publishArticleForm.getContent());
        if(StringUtils.isEmpty(content)){
            //正文内容经过xss过滤后为空白
            return ResponseResult.Return(WebResultEmun.CONTENT_XSS_FILTER_EMPTY_ERROR);
        }
        Document document=Jsoup.parse(content);
        //图片处理
        ResponseEntity imgResult=imageProcess(document,publishArticleForm.getWatemark());
        if(!imgResult.isSuccess()){
            return imgResult;
        }
        //正文图片
        article_vo.setImgjs((List<Blog_Image_Vo>)imgResult.getData());
        article_vo.setTitle(publishArticleForm.getTitle());
        BeanUtils.copyProperties(publishArticleForm,article_vo);
        //正文内容
        article_vo.setContent(HtmlUtils.htmlEscape(document.body().html()));
        article_vo.setArtDesc(document.select("p").text().length()<150?document.select("p").text():document.select("p").text().substring(0,150)+"...");
        article_vo.setPublishTime(new Date());
        article_vo.setCacheKey(StrUtil.cache_key());
        redisUtils.hashPushHashMap(PublicKey.ARTICLE_DATA_MAP,article_vo.getCacheKey(),JSON.toJSONString(article_vo));
        return ResponseResult.Return(article_vo);
    }
}
